package edu.gatech.ors.mrsim.core.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import edu.gatech.ors.mrsim.core.Event;
import edu.gatech.ors.mrsim.core.Node;
import edu.gatech.ors.mrsim.core.SimFile;

public class FileUserNode extends Node {
	private HashMap<String, SimFile> filesToWrite;
	private HashMap<String, SimFile> filesRetrieved;
	private ArrayList<String> toRetrieve;

	public FileUserNode(String ID) {
		super(ID);
		filesToWrite = new HashMap<String, SimFile>();
		filesRetrieved = new HashMap<String, SimFile>();
		toRetrieve = new ArrayList<String>();
	}

	@Override
	public List<Event<?>> respondToEventCompletion(Event<?> event) {
		if (event == null)
			return null;
		if (event instanceof FileRequest) {
			return respondToFileRequestFinish((FileRequest) event);
		}
		return null;
	}

	public void addFileToWrite(SimFile add) {
		filesToWrite.put(add.getName(), add);
	}

	public void addFileToRetrive(String retrieve) {
		toRetrieve.add(retrieve);
	}

	protected List<Event<?>> respondToIOFinish(IORequest event) {
		alterTime(event.getDuration());
		ArrayList<Event<?>> events = new ArrayList<Event<?>>();
		if (!event.isWrite()) {
			filesRetrieved.put(event.getFileName(), (SimFile) event.getData());
			toRetrieve.remove(toRetrieve.indexOf(event.getNodeName()));
		} else {
			filesToWrite.remove(event.getNodeName());
		}
		if (!toRetrieve.isEmpty()) {
			events.add(new FileRequest(currentTime, this, toRetrieve.get(0)));
		} else if (!filesToWrite.isEmpty()) {
			String toWrite = (String) filesToWrite.keySet().toArray()[0];
			events.add(new FileRequest(currentTime, this, toWrite, true));
		}
		return events;
	}

	protected List<Event<?>> respondToFileRequestFinish(FileRequest event) {
		alterTime(event.getDuration());
		String[] names = event.getResponse();
		if (names != null) {
			String fileName = event.getFileName();
			ArrayList<Event<?>> events = new ArrayList<Event<?>>();
			int ask = (int) (Math.random() * names.length);
			if (filesToWrite.keySet().contains(event.getFileName())) {
				events.add(new IORequest(this.getTime(), this, names[ask], fileName, filesToWrite.get(fileName)));
			} else
				events.add(new IORequest(this.getTime(), this, names[ask], fileName));
			return events;
		}
		return null;
	}
}
